JBoss Community Archive (Read Only)

Errai

Messaging API Basics

The MessageBuilder is the heart of the messaging API in ErraiBus. It provides a fluent / builder API, that is used for constructing messages. All three major message patterns can be constructed from the MessageBuilder.

Components that want to receive messages need to implement the MessageCallback interface.

But before we dive into the details, let's look at some use cases first.

Sending Messages with the Client Bus

In order to send a message from a client you need to create a Message and send it through an instance of MessageBus. In this simple example we send it to the subject 'HelloWorldService'.

public class HelloWorld implements EntryPoint {

  // Get an instance of the RequestDispatcher
  private RequestDispatcher dispatcher = ErraiBus.getDispatcher();

  public void onModuleLoad() {
    Button button = new Button("Send message");

    button.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        // Send a message to the 'HelloWorldService'.
        MessageBuilder.createMessage()
          .toSubject("HelloWorldService") // (1)
          .signalling() // (2)
          .noErrorHandling() // (3)
          .sendNowWith(dispatcher); // (4)
        });

        [...]
      }
   }
}

In the above example we build and send a message every time the button is clicked. Here's an explanation of what's going on as annotated above:

  1. We specify the subject we wish to send a message to. In this case, "HelloWorldService".

  2. We indicate that we wish to only signal the service, meaning, that we're not sending a qualifying command to the service. For information on this, read the section on Protocols.

  3. We indicate that we do not want to provide an ErrorCallback to deal with errors for this message.

  4. We transmit the message by providing an instance to the RequestDispatcher

An astute observer will note that access to the RequestDispatcher differs within client code and server code. Because the client code does not run within a container, access to the RequestDispatcher and MessageBus is statically accessed using the ErraiBus.get() and ErraiBus.getDispatcher() methods. The server-side code, conversely, runs inside a dependency container for managing components. See the section on Errai IOC and Errai CDI for using ErraiBus from a client-side container.

When using Errai IOC or CDI, you can also use the Sender<T> interface to send messages.

Receiving Messages on the Server Bus / Server Services

Every message has a sender and at least one receiver. A receiver is as it sounds--it receives the message and does something with it. Implementing a receiver (also referred to as a service) is as simple as implementing our standard MessageCallback interface, which is used pervasively across, both client and server code. Let's begin with server side component that receives messages:

@Service
  public class HelloWorldService implements MessageCallback {
    public void callback(Message message) {
      System.out.println("Hello, World!");
    }
  }

He we declare an extremely simple service. The @Service annotation provides a convenient, meta-data based way of having the bus auto-discover and deploy the service.

Sending Messages with the Server Bus

In the following example we extend our server side component to reply with a message when the callback method is invoked. It will create a message and address it to the subject 'HelloWorldClient':

@Service
public class HelloWorldService implements MessageCallback {

  private RequestDispatcher dispatcher;

  @Inject
  public HelloWorldService(RequestDispatcher dispatcher) {
    dispatcher = dispatcher;
  }

  public void callback(CommandMessage message) {
    // Send a message to the 'HelloWorldClient'.
    MessageBuilder.createMessage()
      .toSubject("HelloWorldClient") // (1)
      .signalling()                  // (2)
      .with("text", "Hi There")      // (3)
      .noErrorHandling()             // (4)
      .sendNowWith(dispatcher);      // (5)
    });
  }
}

The above example shows a service which sends a message in response to receiving a message. Here's what's going on:

  1. We specify the subject we wish to send a message to. In this case, "HelloWorldClient". We are sending this message to all clients which are listening in on this subject. For information on how to communicate with a single client, see Section 2.6.

  2. We indicate that we wish to only signal the service, meaning that we're not sending a qualifying command to the service. For information on this, read the section on Protocols.

  3. We add a message part called "text" which contains the value "Hi there".

  4. We indicate that we do not want to provide an ErrorCallback to deal with errors for this message.

  5. We transmit the message by providing an instance of the RequestDispatcher.

Receiving Messages on the Client Bus/ Client Services

Messages can be received asynchronously and arbitriraily by declaring callback services within the client bus. As ErraiBus maintains an open COMET channel at all times, these messages are delivered in real time to the client as they are sent. This provides built-in push messaging for all client services.

public class HelloWorld implements EntryPoint {

  private MessageBus bus = ErraiBus.get();

  public void onModuleLoad() {
     [...]

     /*
      * Declare a service to receive messages on the subject
      * "BroadcastReceiver".
      */
     bus.subscribe("BroadcastReceiver", new MessageCallback() {
       public void callback(CommandMessage message) {
         /*
          * When a message arrives, extract the "text" field and
          * do something with it
          */
          String messageText = message.get(String.class, "text");
        }
     });

     [...]
  }
}

In the above example, we declare a new client service called "BroadcastReceiver" which can now accept both local messages and remote messages from the server bus. The service will be available in the client to receive messages as long the client bus is and the service is not explicitly de-registered.

Local Services

On the client or the server, you can create a local receiver which only receives messages that originated on the local bus. A local server-side service only receives messages that originate on that server, and a local client-side service only receives messages that originated on that client.

To create a local receiver using the declarative API, use the @Local annotation in conjunction with @Service:

@Local
@Service
  public class HelloIntrovertService implements MessageCallback {
    public void callback(Message message) {
      System.out.println("Hello, me!");
    }
  }

To create a local receiver using through programmatic service registration, use the subscribeLocal() method in place of subscribe():

public void registerLocalService(MessageBus bus) {
  bus.subscribeLocal("LocalBroadcastReceiver", new MessageCallback() {
    public void callback(Message message) {
       String messageText = message.get(String.class, "text");
     }
  });
}

Both examples above work in client- and server-side code.

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-10 12:34:44 UTC, last content change 2013-10-01 19:40:30 UTC.